package com.mask.token.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Token动态配置服务
 * 支持运行时配置更新、配置热重载等功能
 *
 * @author mask
 * @since 1.0.0
 */
@Slf4j
@Configuration
@EnableScheduling
@ConditionalOnProperty(name = "mask.token.dynamic.enabled", havingValue = "true", matchIfMissing = false)
public class MaskTokenDynamicConfig {

    // 动态配置缓存
    private final ConcurrentHashMap<String, DynamicConfigItem> configCache = new ConcurrentHashMap<>();
    
    // 配置更新监听器
    private final ConcurrentHashMap<String, ConfigUpdateListener> listeners = new ConcurrentHashMap<>();

    /**
     * 动态配置项
     */
    public static class DynamicConfigItem {
        private String key;
        private Object value;
        private String type;
        private Instant lastUpdated;
        private boolean active;

        public DynamicConfigItem(String key, Object value, String type) {
            this.key = key;
            this.value = value;
            this.type = type;
            this.lastUpdated = Instant.now();
            this.active = true;
        }

        // Getters and Setters
        public String getKey() { return key; }
        public void setKey(String key) { this.key = key; }
        public Object getValue() { return value; }
        public void setValue(Object value) { this.value = value; }
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        public Instant getLastUpdated() { return lastUpdated; }
        public void setLastUpdated(Instant lastUpdated) { this.lastUpdated = lastUpdated; }
        public boolean isActive() { return active; }
        public void setActive(boolean active) { this.active = active; }
    }

    /**
     * 配置更新监听器
     */
    public interface ConfigUpdateListener {
        void onConfigUpdate(String key, Object oldValue, Object newValue);
    }

    /**
     * 更新动态配置
     */
    public void updateConfig(String key, Object value, String type) {
        try {
            DynamicConfigItem oldItem = configCache.get(key);
            DynamicConfigItem newItem = new DynamicConfigItem(key, value, type);
            
            configCache.put(key, newItem);
            
            // 通知监听器
            if (oldItem != null) {
                notifyListeners(key, oldItem.getValue(), value);
            }
            
            log.info("动态配置已更新: {} = {} ({})", key, value, type);
        } catch (Exception e) {
            log.error("更新动态配置失败: {}", key, e);
        }
    }

    /**
     * 获取动态配置
     */
    public Object getConfig(String key) {
        DynamicConfigItem item = configCache.get(key);
        return item != null && item.isActive() ? item.getValue() : null;
    }

    /**
     * 获取动态配置（带默认值）
     */
    public Object getConfig(String key, Object defaultValue) {
        Object value = getConfig(key);
        return value != null ? value : defaultValue;
    }

    /**
     * 获取字符串配置
     */
    public String getStringConfig(String key, String defaultValue) {
        Object value = getConfig(key, defaultValue);
        return value != null ? value.toString() : defaultValue;
    }

    /**
     * 获取整数配置
     */
    public Integer getIntConfig(String key, Integer defaultValue) {
        Object value = getConfig(key, defaultValue);
        if (value instanceof Integer) {
            return (Integer) value;
        } else if (value instanceof String) {
            try {
                return Integer.parseInt((String) value);
            } catch (NumberFormatException e) {
                log.warn("配置值不是有效的整数: {} = {}", key, value);
                return defaultValue;
            }
        }
        return defaultValue;
    }

    /**
     * 获取布尔配置
     */
    public Boolean getBooleanConfig(String key, Boolean defaultValue) {
        Object value = getConfig(key, defaultValue);
        if (value instanceof Boolean) {
            return (Boolean) value;
        } else if (value instanceof String) {
            return Boolean.parseBoolean((String) value);
        }
        return defaultValue;
    }

    /**
     * 获取持续时间配置
     */
    public Duration getDurationConfig(String key, Duration defaultValue) {
        Object value = getConfig(key, defaultValue);
        if (value instanceof Duration) {
            return (Duration) value;
        } else if (value instanceof String) {
            try {
                return Duration.parse((String) value);
            } catch (Exception e) {
                log.warn("配置值不是有效的持续时间: {} = {}", key, value);
                return defaultValue;
            }
        }
        return defaultValue;
    }

    /**
     * 注册配置更新监听器
     */
    public void registerListener(String key, ConfigUpdateListener listener) {
        listeners.put(key, listener);
        log.debug("配置更新监听器已注册: {}", key);
    }

    /**
     * 移除配置更新监听器
     */
    public void removeListener(String key) {
        listeners.remove(key);
        log.debug("配置更新监听器已移除: {}", key);
    }

    /**
     * 获取所有配置
     */
    public ConcurrentHashMap<String, DynamicConfigItem> getAllConfigs() {
        return new ConcurrentHashMap<>(configCache);
    }

    /**
     * 清理过期配置
     */
    @Scheduled(fixedRate = 300000) // 每5分钟执行一次
    public void cleanExpiredConfigs() {
        try {
            Instant cutoffTime = Instant.now().minusSeconds(3600); // 1小时前
            
            configCache.entrySet().removeIf(entry -> {
                DynamicConfigItem item = entry.getValue();
                return !item.isActive() && item.getLastUpdated().isBefore(cutoffTime);
            });
            
            log.debug("清理过期配置完成，剩余配置数: {}", configCache.size());
        } catch (Exception e) {
            log.error("清理过期配置失败", e);
        }
    }

    /**
     * 通知监听器配置更新
     */
    private void notifyListeners(String key, Object oldValue, Object newValue) {
        ConfigUpdateListener listener = listeners.get(key);
        if (listener != null) {
            try {
                listener.onConfigUpdate(key, oldValue, newValue);
            } catch (Exception e) {
                log.error("通知配置更新监听器失败: {}", key, e);
            }
        }
    }

    /**
     * 初始化默认配置
     */
    public void initializeDefaultConfigs() {
        // Token相关配置
        updateConfig("token.secret", "mask-token-secret-key-2024", "string");
        updateConfig("token.access-token-validity", "PT2H", "duration");
        updateConfig("token.refresh-token-validity", "P7D", "duration");
        updateConfig("token.auto-renewal", true, "boolean");
        updateConfig("token.renewal-threshold", "PT30M", "duration");
        updateConfig("token.max-sessions", 3, "integer");
        
        // 安全相关配置
        updateConfig("security.enable-cors", true, "boolean");
        updateConfig("security.enable-csrf", false, "boolean");
        updateConfig("security.allowed-origins", "*", "string");
        
        // 性能相关配置
        updateConfig("performance.cache-enabled", true, "boolean");
        updateConfig("performance.cache-ttl", "PT5M", "duration");
        updateConfig("performance.async-enabled", false, "boolean");
        
        // 监控相关配置
        updateConfig("monitor.enabled", false, "boolean");
        updateConfig("monitor.retention-hours", 24, "integer");
        updateConfig("monitor.detailed-logging", false, "boolean");
        
        log.info("默认配置已初始化，配置项数量: {}", configCache.size());
    }
}
